Load Libraries

library(osmdata)
library(opentripplanner)
library(tidyverse)
library(sf)
library(ggthemes)
library(ggspatial)
library(data.table)
library(png)
library(grid)
library(ggimage)
library(ggrepel)

Preparing Document

WGS <- '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
dogs <- read.csv("Dogs_of_Cambridge.csv")
dogs1 <- st_as_sf(x = dogs, coords = c("long", "lat"), crs = WGS)

Get Street Data

cambridge_street_query <- opq(bbox = 'Cambridge MA USA') %>%
  add_osm_feature(key = 'highway')

cambridge_street_query %>%
  osmdata_xml(file = 'OTP/graphs/default/cambridge_streets.osm')

cambridge_street_features <- cambridge_street_query %>%
  osmdata_sf()

cambridge_streets <- cambridge_street_features$osm_lines %>%
  st_transform(crs = WGS)

Plot Data

ggplot(cambridge_streets) +
  geom_sf()+
  theme_map()

OTP Java Trip Planner Download

path_otp <- otp_dl_jar("OTP")

Build a Graph

path_data <- file.path(getwd(), "OTP")
path_otp <- paste(path_data, "otp.jar", sep = "/")

otp_build_graph(otp = path_otp, dir = path_data, memory = 1024)

Launch OTP

otp_setup(otp = path_otp, dir = path_data, memory = 1024)

# Connect to opentripplanner
otpcon <- otp_connect()

Create Isochrone for 5 min walk, bike, and drive

iso_5min_walk <- 
  otp_isochrone(otpcon = otpcon, fromPlace = dogs1, 
                mode = "WALK", cutoffSec = 300) %>%
  st_transform(crs = WGS) %>%
  mutate(mode = "walk")
iso_5min_bike <- 
  otp_isochrone(otpcon = otpcon, fromPlace = dogs1, 
                mode = "BICYCLE", cutoffSec = 300) %>%
  st_transform(crs = WGS) %>%
  mutate(mode = "bike")
iso_5min_drive <- 
  otp_isochrone(otpcon = otpcon, fromPlace = dogs1, 
                mode = "CAR", cutoffSec = 300) %>%
  st_transform(crs = WGS) %>%
  mutate(mode = "drive")

iso_all_modes <- rbind(iso_5min_drive, iso_5min_bike, iso_5min_walk)
right_side <- st_bbox(iso_all_modes)$xmax
left_side  <- st_bbox(iso_all_modes)$xmin
top_side <- st_bbox(iso_all_modes)$ymax
bottom_side <- st_bbox(iso_all_modes)$ymin

ggplot(iso_all_modes) +
  annotation_map_tile(type = "cartolight", zoomin = 0, progress = "none") +
  geom_sf(aes(fill = mode), color = "NA", alpha = 0.5) +
  coord_sf(xlim = c(left_side, right_side), 
           ylim = c(bottom_side, top_side), expand = FALSE) +
  scale_fill_manual(values = c("lightgoldenrod1", "tan2", "orangered3"),
                     name = "Corgis that are reachable\nwithin 5 minutes",
                       labels = c("By car", "By Bike", "By foot")) +
  theme_map() +
  theme(legend.background = element_blank(), legend.position = "left") +
  labs(caption = "Basemap Copyright OpenStreetMap contributors")
## Loading required namespace: raster

Areas Within a 5 minute bike and walk of each Corgi

dogs1$image <- "corgi1.png"
iso_areas <- iso_all_modes %>%
  mutate(area = st_area(iso_all_modes)) %>%
  st_set_geometry(NULL) %>%
  pivot_wider(names_from = mode, values_from = area) 

ggplot(iso_areas, 
       aes(x = as.numeric(walk), y = as.numeric(bike))) +
  geom_point() +
    geom_image(aes(image = "corgi1.png"), size = .07, asp = 1.3)+
  scale_x_continuous(name = 
            "Area within a five-minute walking distance of a corgi\n(square km)",
            breaks = breaks <- seq(10000, 130000, by = 20000),
            labels = breaks / 1000000) +
  scale_y_continuous(name = 
            "Area within a five-minute biking distance of a corgi\n(square km)",
            breaks = breaks <- seq(0, 700000, by = 100000),
            labels = breaks / 1000000) +
  theme_pander()
## Warning: Removed 5 rows containing missing values (geom_point).
## Warning: Removed 5 rows containing missing values (geom_image).

Areas Within a 10 minute bike and walk of each Corgi

iso_10min_bike <- 
  otp_isochrone(otpcon = otpcon, fromPlace = dogs1, 
                mode = "BICYCLE", cutoffSec = 600) %>%
  st_transform(crs = WGS) %>%
  mutate(mode = "bike")
iso_10min_walk <- 
  otp_isochrone(otpcon = otpcon, fromPlace = dogs1, 
                mode = "WALK", cutoffSec = 600) %>%
  st_transform(crs = WGS) %>%
  mutate(mode = "walk")
iso_all_modes_10 <- rbind(iso_10min_bike, iso_10min_walk)
dogs1$image <- "corgi.png"
iso_areas10 <- iso_all_modes_10 %>%
  mutate(area = st_area(iso_all_modes_10)) %>%
  st_set_geometry(NULL) %>%
  pivot_wider(names_from = mode, values_from = area) 

ggplot(iso_areas10, 
       aes(x = as.numeric(walk), y = as.numeric(bike))) +
  geom_point() +
  geom_image(aes(image = "corgi.png"), size = .08, asp = 1.2)+
  scale_x_continuous(name = 
            "Area within a ten-minute walking distance of a corgi\n(square km)",
            breaks = breaks <- seq(10000, 130000, by = 20000),
            labels = breaks / 1000000) +
  scale_y_continuous(name = 
            "Area within a ten-minute biking distance of a corgi\n(square km)",
            breaks = breaks <- seq(0, 700000, by = 100000),
            labels = breaks / 1000000) +
  theme_economist()

Merged areas for 10 minute Isochrones

total_area_walk<- st_as_sf(st_union(iso_10min_walk$geometry))
ggplot(total_area_walk) +
  annotation_map_tile(type = "cartolight", zoomin = 0, progress = "none") +
  geom_sf(fill = "lightgoldenrod1", color = "NA", alpha = 0.5) +
  geom_sf(data = dogs1, size = 2, color = "tan3") +
  annotate(geom = "text", x = left_side + .045, 
           y = top_side, 
           label = paste("Overlapping Corgi 10 minute Walksheds"), 
           hjust = 0, vjust = 0, size = 3) +
  theme_map() +
  labs(caption = "Basemap Copyright OpenStreetMap contributors") 

10 minute Isochrones and Open Space

openspace <- st_read("https://data.cambridgema.gov/api/geospatial/q73m-a5e2?method=export&format=KML")
## Reading layer `Layer #0' from data source `https://data.cambridgema.gov/api/geospatial/q73m-a5e2?method=export&format=KML' using driver `KML'
## Simple feature collection with 249 features and 2 fields
## geometry type:  MULTIPOLYGON
## dimension:      XY
## bbox:           xmin: -71.15971 ymin: 42.35298 xmax: -71.06624 ymax: 42.40436
## geographic CRS: WGS 84
ggplot(total_area_walk) +
  annotation_map_tile(type = "cartolight", zoomin = 0, progress = "none") +
  geom_sf(fill = "lightgoldenrod1", color = "NA", alpha = 0.5) +
  geom_sf(data = dogs1, size = 2, color = "tan3") +
  geom_sf(data = openspace, color = "NA", fill = "darkolivegreen3", alpha = 0.5) +
  annotate(geom = "text", x = left_side + .045, 
           y = top_side, 
           label = paste("Corgi 10 minute Walksheds and Open Space"), 
           hjust = 0, vjust = 0, size = 3) +
  theme_map() +
  labs(caption = "Basemap Copyright OpenStreetMap contributors") 

Corgi Areas with Names

I have been trying to combine the next two visualizations, but with no success. I think it would be most effective to have the names with pop-outs but on the map.

map_names <- ggplot() +
  annotation_map_tile(type = "cartolight", zoomin = 0, progress = "none") +
  geom_sf(dogs1, mapping = aes(color = Dog_Name)) +
  scale_color_manual(values = c("darkolivegreen", "seagreen3", "salmon3", "yellow4", "darkorange1", "turquoise", "violet", "royalblue", "steelblue2", "tan", "darkorchid", "chartreuse3", "springgreen4", "cyan3", "firebrick", "lightgoldenrod4", "darkseagreen", "plum", "hotpink", "deeppink", "lightblue4", "tomato", "cadetblue", "black", "thistle4"), 
                    name = element_blank(),
                    labels = c("Andy", "Annie", "Baci", "Bruce", "Cassie", "Frida", "Hazel", "Izzy", "Katie", "Kuma", "Lewi", "Lola", "Louie", "Marvel", "Mia", "Otis", "Rue", "Rupert", "Scout", "Teddy", "Tennessee", "Tomato", "Trixie", "Wilson", "Yo-Yo")) +
  theme_pander()

map_names

map_text <- ggplot(dogs, mapping = aes(x= long, y= lat, label=Dog_Name))+
geom_point() +
theme_map()
map_text

map_text + geom_label_repel(aes(label = Dog_Name),
                            box.padding   = 0.35, 
                  point.padding = 0.5,
                  segment.color = 'grey50') +
  theme_classic()